package models

import (
	"fmt"
	"regexp"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
	"gorm.io/gorm"
)

// Models 数据模型基础结构体
type Models struct {
	ID        uint32    `gorm:"primary_key" json:"id"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

// AutoMigrate 自动迁移数据库表结构
// 参数:
//   - tx: 数据库连接对象
//   - tables: 需要迁移的表结构列表
//
// 返回值:
//   - error: 迁移过程中可能发生的错误
func AutoMigrate(tx *gorm.DB, tables ...interface{}) error {
	return tx.AutoMigrate(tables...)
}

// QueryCondition 查询条件结构体
type QueryCondition struct {
	Field string            // 查询字段名
	Op    map[string]string // 操作符: "=", "like", ">", "<", ">=", "<=", "<>", "in"
	Value interface{}       // 查询值
}

type QueryInfo struct {
	QueryConditions []QueryCondition
	Limit           uint32
	Page            uint32
}

// AdvancedQueryDatabase 支持复杂查询条件的函数
// 参数:
//   - tx: 数据库连接对象
//   - out: 查询结果存储的目标切片指针
//   - conditions: 查询条件列表
//
// 返回值:
//   - error: 查询过程中可能发生的错误
func AdvancedQueryDatabase[T any](tx *gorm.DB, out *[]T, conditions QueryInfo) error {
	query := tx
	for _, cond := range conditions.QueryConditions {
		// 验证字段名，防止SQL注入
		if !isValidFieldName(cond.Field) {
			logx.Error("无效的字段名")
			return fmt.Errorf("invalid field name: %s", cond.Field)
		}

		// 统一处理操作符
		for op, value := range cond.Op {
			switch op {
			case "Fuzzy":
				// 模糊查询，自动添加通配符
				query = query.Where(fmt.Sprintf("%s LIKE ?", cond.Field), "%"+fmt.Sprintf("%v", cond.Value)+"%")
			case "Precise":
				switch value {
				case "=":
					query = query.Where(fmt.Sprintf("%s = ?", cond.Field), cond.Value)
				case "!=":
					query = query.Where(fmt.Sprintf("%s != ?", cond.Field), cond.Value)
				case ">":
					query = query.Where(fmt.Sprintf("%s > ?", cond.Field), cond.Value)
				case "<":
					query = query.Where(fmt.Sprintf("%s < ?", cond.Field), cond.Value)
				case ">=":
					query = query.Where(fmt.Sprintf("%s >= ?", cond.Field), cond.Value)
				case "<=":
					query = query.Where(fmt.Sprintf("%s <= ?", cond.Field), cond.Value)
				case "in":
					query = query.Where(fmt.Sprintf("%s in ?", cond.Field), cond.Value)
				case "not in":
					query = query.Where(fmt.Sprintf("%s not in ?", cond.Field), cond.Value)
				case "<>":
					query = query.Where(fmt.Sprintf("%s <> ?", cond.Field), cond.Value)
				default:
					query = query.Where(fmt.Sprintf("%s = ?", cond.Field), cond.Value)
				}
			}
		}
	}

	limit := conditions.Limit
	offset := (conditions.Page - 1) * conditions.Limit
	result := query.Limit(int(limit)).Offset(int(offset)).Find(out)
	if result.Error != nil {
		logx.Error("高级查询数据失败")
		return result.Error
	}

	if result.RowsAffected == 0 {
		logx.Info("高级查询完成，无匹配数据")
	} else {
		logx.Infof("高级查询数据成功，查询%v条数据", len(*out))
	}
	return nil
}

// isValidFieldName 验证字段名是否合法，防止SQL注入
func isValidFieldName(fieldName string) bool {
	// 字段名只能包含字母、数字和下划线，且不能以数字开头
	match, _ := regexp.MatchString("^[a-zA-Z_][a-zA-Z0-9_]*$", fieldName)
	return match
}

// ... existing code ...

// CreateDatabase 创建数据记录
// 参数:
//   - tx: 数据库连接对象
//   - data: 要插入的数据切片
//
// 返回值:
//   - error: 插入过程中可能发生的错误
func CreateDatabase[T any](tx *gorm.DB, data []T) error {
	if err := tx.Create(&data).Error; err != nil {
		logx.Errorf("插入数据失败，错误信息: %v，数据条数: %v", err, len(data))
		return err
	}
	logx.Infof("插入数据成功，插入%v条数据", len(data))
	return nil
}

// DeleteDatabase 删除数据记录
// 参数:
//   - tx: 数据库连接对象
//   - data: 要删除的数据切片
//
// 返回值:
//   - error: 删除过程中可能发生的错误
func DeleteDatabase[T any](tx *gorm.DB, data []T) error {
	if err := tx.Delete(&data).Error; err != nil {
		logx.Errorf("删除数据失败，错误信息: %v，数据条数: %v", err, len(data))
		return err
	}
	logx.Infof("删除数据成功，删除%v条数据", len(data))
	return nil
}

// QueryDatabase 根据条件查询数据记录
// 参数:
//   - tx: 数据库连接对象
//   - out: 查询结果存储的目标切片指针
//   - where: 查询条件键值对
//
// 返回值:
//   - error: 查询过程中可能发生的错误
func QueryDatabase[T any](tx *gorm.DB, out *[]T, where map[string]interface{}) error {
	result := tx.Where(where).Find(out)
	if result.Error != nil {
		logx.Errorf("查询数据失败，错误信息: %v，查询条件: %v", result.Error, where)
		return result.Error
	}

	if result.RowsAffected == 0 {
		logx.Infof("查询完成，无匹配数据，查询条件: %v", where)
	} else {
		logx.Infof("查询数据成功，查询%v条数据，查询条件: %v", len(*out), where)
	}
	return nil
}

// UpdateDatabase 根据条件更新数据记录
// 参数:
//   - tx: 数据库连接对象
//   - data: 要更新的数据对象
//   - where: 更新条件键值对
//
// 返回值:
//   - error: 更新过程中可能发生的错误
func UpdateDatabase[T any](tx *gorm.DB, data T, where map[string]interface{}) error {
	result := tx.Where(where).Updates(&data)
	if result.Error != nil {
		logx.Errorf("更新数据失败，错误信息: %v，更新条件: %v", result.Error, where)
		return result.Error
	}
	logx.Infof("更新数据成功，影响行数: %v，更新条件: %v", result.RowsAffected, where)
	return nil
}

// SelectiveUpdateDatabase 支持选择性更新零值字段
// 参数:
//   - tx: 数据库连接对象
//   - data: 要更新的数据对象
//   - where: 更新条件键值对
//   - selectFields: 指定需要更新的字段列表
//
// 返回值:
//   - error: 更新过程中可能发生的错误
func SelectiveUpdateDatabase[T any](tx *gorm.DB, data T, where map[string]interface{}, selectFields ...string) error {
	query := tx.Model(&data).Where(where)

	// 如果指定了要更新的字段，则只更新这些字段（包括零值）
	if len(selectFields) > 0 {
		query = query.Select(selectFields)
	}

	result := query.Updates(data)
	if result.Error != nil {
		logx.Errorf("选择性更新数据失败，错误信息: %v，更新条件: %v", result.Error, where)
		return result.Error
	}
	logx.Infof("选择性更新数据成功，影响行数: %v，更新条件: %v", result.RowsAffected, where)
	return nil
}
